#include "tim.h"

TIM_HandleTypeDef htim1;

extern "C" {

void TIM1_PWM_Init(void)
{
    // Enable GPIO and Timer clocks
    __HAL_RCC_GPIOA_CLK_ENABLE();     // Enable GPIOA clock
    __HAL_RCC_GPIOB_CLK_ENABLE();     // Enable GPIOB clock
    __HAL_RCC_TIM1_CLK_ENABLE();      // Enable TIM1 clock

    // Configure GPIO pins for TIM1
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // Configure PWM outputs (PA8,PA9,PA10)
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;  
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;     
    GPIO_InitStruct.Pull = GPIO_NOPULL;         
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;  
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;  
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // Configure Break Input pin (PB12)
    GPIO_InitStruct.Pin = GPIO_PIN_12;            // PB12 as Break input
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;       // Alternate Function Push Pull
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;         // Pull-down to prevent floating
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // High speed
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;    // TIM1 Break function
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // Configure Timer base
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 0;                        
    htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;  // Back to center-aligned mode 1
    htim1.Init.Period = 8499;                       // For 5kHz: 170MHz/2/(10kHz)-1
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;  // No clock division
    htim1.Init.RepetitionCounter = 0;                // No repetition
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;  // Disable preload
    HAL_TIM_PWM_Init(&htim1);

    // Configure PWM channels 1-3
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;          // PWM mode 1 (active when counter < compare)
    sConfigOC.Pulse = 0;                         // Initial duty cycle = 0
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;  // Active high polarity
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;   // Disable fast mode
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;  // Low level when idle
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

    // Configure CH1-3 for normal PWM output
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);  // Configure CH1
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);  // Configure CH2
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);  // Configure CH3

    // Configure CH4 for one trigger per PWM period
    sConfigOC.OCMode = TIM_OCMODE_PWM2;          // PWM mode 2 - active when counter > compare
    sConfigOC.Pulse = 7499;                      // Trigger at middle of up-counting (16999/2)
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4);

    // Configure TRGO to use OC4REF
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF;     // Use OC4REF for TRGO
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

    // Configure Break feature
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 0;
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;     // Disable break
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.BreakFilter = 0;
    sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT;
    sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;   // Disable break2
    sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
    sBreakDeadTimeConfig.Break2Filter = 0;
    sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
    HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);

    // Start CH4 immediately since it has fixed duty cycle
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);    // Start CH4 PWM generation
    __HAL_TIM_MOE_ENABLE(&htim1);                // Enable main output
}

void TIM1_Start(void)
{
    // Clear break interrupt and start timer base
    __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_BREAK);
    HAL_TIM_Base_Start(&htim1);
    
    // Start CH4 for ADC triggering
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
}

void TIM1_SetCompare(uint32_t channel, uint32_t value)
{
    __HAL_TIM_SET_COMPARE(&htim1, channel, value);  // Set compare value
}

} // extern "C"
